package com.zl.tby.screen.service.impl;

import com.zl.tby.core.base.util.PgMountains;
import com.zl.tby.core.base.util.ToolsUtil;
import com.zl.tby.dto.TbyUavRecordQuery;
import com.zl.tby.model.TbyUavInfo;
import com.zl.tby.screen.enums.TbyReportEventEnum;
import com.zl.tby.screen.service.ITbyMountainsScreenService;
import com.zl.tby.screen.vo.mountains.*;
import com.zl.tby.service.ITbyUavInfoService;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.wood.DataItem;
import org.noear.wood.DbContext;
import org.noear.wood.annotation.Db;
import org.noear.wood.utils.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * 巡山护林大屏 impl
 * @author changpeng
 * @version 1.0
 * @since 2024/8/20 10:33
 */
@Component
public class TbyMountainsScreenServiceImpl implements ITbyMountainsScreenService {

    @Db
    private DbContext db;

    @Override
    public TbyMountainsScreenBean flightData(TbyUavRecordQuery query) {
        try {
            if (query.getUavId() == null || StringUtils.isEmpty(query.getUseDateEnd()) || StringUtils.isEmpty(query.getUseDateBegin())) {
                return TbyMountainsScreenBean.initFlightData();
            }
            List<TbyMountainsScreenBean> dataList = db.table("tby_uav_record").whereEq("uav_id", query.getUavId())
                    .andIf(StringUtils.isNotEmpty(query.getUseDateBegin()), "use_date >= ?", query.getUseDateBegin() + " 00:00:00")
                    .andIf(StringUtils.isNotEmpty(query.getUseDateEnd()), "use_date <= ?", query.getUseDateEnd() + " 23:59:59")
                    .groupBy("uav_id")
                    .selectList("uav_id id, count(id) flight_count, sum(flight_distance) flight_distance, sum(flight_time) flight_time", TbyMountainsScreenBean.class);
            return dataList == null || dataList.size() == 0 ? TbyMountainsScreenBean.initFlightData() : dataList.get(0);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return TbyMountainsScreenBean.initFlightData();
    }

    @Override
    public List<TbyMountainsScreenBean> flightTaskData(TbyUavRecordQuery query) {
        try {
            if (StringUtils.isEmpty(query.getUseDateEnd()) || StringUtils.isEmpty(query.getUseDateBegin())) {
                return new ArrayList<>();
            }
            List<TbyMountainsScreenBean> dataList = db.table("tby_uav_record").whereTrue()
                    .andIf(StringUtils.isNotEmpty(query.getUseDateBegin()), "use_date >= ?", query.getUseDateBegin() + " 00:00:00")
                    .andIf(StringUtils.isNotEmpty(query.getUseDateEnd()), "use_date <= ?", query.getUseDateEnd() + " 23:59:59")
                    .groupBy("task_code")
                    .selectList("task_code, count(id) flight_count", TbyMountainsScreenBean.class);
            if (dataList == null || dataList.size() == 0) {
                return new ArrayList<>();
            }
            long total = 0;
            for (TbyMountainsScreenBean entity : dataList) {
                if (entity.getFlightCount() != null) {
                    total = entity.getFlightCount().longValue() + total;
                }
            }
            for (TbyMountainsScreenBean item : dataList) {
                item.setTotal(total);
                item.cal();
            }
            Collections.sort(dataList, Comparator.comparingDouble(TbyMountainsScreenBean::getPercentage).reversed());
            TbyMountainsScreenBean.resetPercentage(dataList);
            return dataList;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return new ArrayList<>();
    }

    @Override
    public List<TbyMountainsPerson> personList() {
        StringBuilder builder = new StringBuilder();
        builder.append("select u.i_userid as \"personId\", u.c_userealname as \"realName\", u.user_sex as \"sex\", u.c_usertel as \"phone\"")
                .append(" , online.is_online as \"isOnline\", online.longitude, online.latitude, online.lasttime as \"lastTime\"")
                .append(" from xh_ht.fs_yw_base_user u")
                .append(" left join xh_yw.xh_user_online_tb online on u.i_userid = online.i_userid")
                .append(" where u.i_orgid in (734) and u.pyzt in ('10', '30')");
        PgMountains<TbyMountainsPerson> pgMountains = new PgMountains<>();
        List<TbyMountainsPerson> dataList = pgMountains.query(builder.toString(), TbyMountainsPerson.class);
        TbyMountainsPerson.convert(dataList);
        return dataList;
    }

    @Override
    public TbyPatrolStatisticBean patrolStatistic(String startTime, String endTime, Long userId) {
        StringBuilder builder = new StringBuilder();
        builder.append("select") .append(" count(id) as \"time\"")
                        .append(", count(i_userid) as \"personCount\"")
                        .append(", sum(track_time) as \"duration\"")
                        .append(", sum(track_distance) as \"distance\"")
                        .append(" from xh_yw.xh_track_tb where 1 = 1");
        List<Object> params = new ArrayList<>();
        if (StringUtils.isNotEmpty(startTime)) {
            builder.append(" and start_time >= ?");
            params.add(ToolsUtil.dateString2Util(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            builder.append(" and end_time <= ?");
            params.add(ToolsUtil.dateString2Util(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }
        if (userId != null) {
            builder.append(" and i_userid = ?");
            params.add(userId);
        }
        PgMountains<TbyPatrolStatisticBean> pgMountains = new PgMountains<>();
        List<TbyPatrolStatisticBean> dataList = pgMountains.query(builder.toString(), params, TbyPatrolStatisticBean.class);
        if (dataList != null && dataList.size() > 0) {
            dataList.get(0).convert();
            return dataList.get(0);
        }
        return TbyPatrolStatisticBean.init();
    }

    @Override
    public List<TbyPatrolStatisticBean> patrolStatisticGroupByUserId(String startTime, String endTime) {
        StringBuilder builder = new StringBuilder();
        builder.append("select") .append(" i_userid as \"userId\", count(id) as \"time\"")
                .append(", count(i_userid) as \"personCount\"")
                .append(", sum(track_time) as \"duration\"")
                .append(", sum(track_distance) as \"distance\"")
                .append(" from xh_yw.xh_track_tb where 1 = 1");
        List<Object> params = new ArrayList<>();
        if (StringUtils.isNotEmpty(startTime)) {
            builder.append(" and start_time >= ?");
            params.add(ToolsUtil.dateString2Util(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            builder.append(" and end_time <= ?");
            params.add(ToolsUtil.dateString2Util(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }
        builder.append(" group by i_userid");
        PgMountains<TbyPatrolStatisticBean> pgMountains = new PgMountains<>();
        List<TbyPatrolStatisticBean> dataList = pgMountains.query(builder.toString(), params, TbyPatrolStatisticBean.class);
        if (dataList != null && dataList.size() > 0) {
            dataList.forEach(item -> {
                item.convert();
            });
        }
        return dataList;
    }

    @Override
    public TbyReportEventBean reportEvent(String startTime, String endTime) {
        TbyReportEventBean result = new TbyReportEventBean();
        // 拼接条件
        StringBuilder whereBuild = new StringBuilder();
        whereBuild.append(" where 1 = 1");
        List<Object> params = new ArrayList<>();
        if (StringUtils.isNotEmpty(startTime)) {
            whereBuild.append(" and uploade_time >= ?");
            params.add(ToolsUtil.dateString2Util(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            whereBuild.append(" and uploade_time <= ?");
            params.add(ToolsUtil.dateString2Util(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }
        String where = whereBuild.toString();
        PgMountains db = new PgMountains();
        TbyReportEventQuery query = new TbyReportEventQuery();
        query.setParams(params);
        query.setWhere(where);
        // 毁坏林地
        result.setWoodland(TbyReportEventEnum.woodland.count(db, query));
        // 毁坏林木
        result.setForest(TbyReportEventEnum.forest.count(db, query));
        // 森林防火
        result.setFireproof(TbyReportEventEnum.fireproof.count(db, query));
        // 野生动植物
        result.setAnimalsPlants(TbyReportEventEnum.animalsPlants.count(db, query));
        // 有害生物
        result.setPest(TbyReportEventEnum.pest.count(db, query));
        // 自然灾害
        result.setNaturalDisaster(TbyReportEventEnum.naturalDisaster.count(db, query));
        // 核实无异常
        result.setNoError(TbyReportEventEnum.noError.count(db, query));
        return result;
    }

    @Override
    public List<TbyReportEventInformation> reportEventList(String eventType, String startTime, String endTime) {
        // 拼接条件
        StringBuilder whereBuild = new StringBuilder();
        whereBuild.append(" where 1 = 1");
        List<Object> params = new ArrayList<>();
        if (StringUtils.isNotEmpty(startTime)) {
            whereBuild.append(" and uploade_time >= ?");
            params.add(ToolsUtil.dateString2Util(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            whereBuild.append(" and uploade_time <= ?");
            params.add(ToolsUtil.dateString2Util(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }
        String where = whereBuild.toString();
        PgMountains db = new PgMountains();
        TbyReportEventQuery query = new TbyReportEventQuery();
        query.setParams(params);
        query.setWhere(where);
        TbyReportEventEnum tbyReportEventEnum = TbyReportEventEnum.getByCode(eventType);
        if (tbyReportEventEnum == null) {
            return new ArrayList<>();
        }
        List<TbyReportEventInformation> dataList = tbyReportEventEnum.findList(db, query);
        if (dataList != null) {
            for (TbyReportEventInformation entity : dataList) {
                entity.convert();
            }
        }
        return dataList;
    }

    @Override
    public List<TbyReportAttachBean> reportFileList(String eventGuid) {
        String sql = "select file_type AS \"fileType\", file_url AS \"fileUrl\", file_thumbnail_url AS \"thumbnailUrl\", source_type AS \"sourceType\" from xh_yw.xh_event_file_tb where event_guid = ?";
        List<Object> params = new ArrayList<>();
        params.add(eventGuid);
        PgMountains<TbyReportAttachBean> db = new PgMountains<>();
        return db.query(sql, params, TbyReportAttachBean.class);
    }

    @Override
    public List<List<Map<String, BigDecimal>>> track(String startTime, String endTime) {
        StringBuilder builder = new StringBuilder();
        builder.append("select st_astext(geo_track) as geo_track from xh_yw.xh_track_tb where 1 = 1");
        List<Object> params = new ArrayList<>();
        if (StringUtils.isNotEmpty(startTime)) {
            builder.append(" and start_time >= ?");
            params.add(ToolsUtil.dateString2Util(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            builder.append(" and end_time <= ?");
            params.add(ToolsUtil.dateString2Util(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }
        builder.append(" order by id desc limit 200");
        List<List<Map<String, BigDecimal>>> resultList = new ArrayList<>();
        PgMountains db = new PgMountains();
        List<Map<String, Object>> dbList = db.queryMap(builder.toString(), params);
        for (Map<String, Object> stringObjectMap : dbList) {
            String track = (String) stringObjectMap.get("geo_track");
            if (track != null) {
                track = ToolsUtil.replaceStr(track, "LINESTRING(", "");
                track = ToolsUtil.replaceStr(track, ")", "");
                String[] array = ToolsUtil.splitStr(track, ',');
                List<Map<String, BigDecimal>> pointList = new ArrayList<>();
                for (String s : array) {
                    String[] point = ToolsUtil.splitStr(s.trim(), ' ');
                    Map<String, BigDecimal> map = new HashMap<>(2);
                    map.put("lon", new BigDecimal(point[0]));
                    map.put("lat", new BigDecimal(point[1]));
                    pointList.add(map);
                }
                resultList.add(pointList);
            }
        }
        return resultList;
    }

    @Override
    public List<Map<String, Object>> trackStr(String startTime, String endTime) {
        StringBuilder builder = new StringBuilder();
        builder.append("select st_astext(geo_track) as geo_track from xh_yw.xh_track_tb where 1 = 1");
        List<Object> params = new ArrayList<>();
        if (StringUtils.isNotEmpty(startTime)) {
            builder.append(" and start_time >= ?");
            params.add(ToolsUtil.dateString2Util(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            builder.append(" and end_time <= ?");
            params.add(ToolsUtil.dateString2Util(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
        }
        List<List<Map<String, BigDecimal>>> resultList = new ArrayList<>();
        PgMountains db = new PgMountains();
        long s = System.currentTimeMillis();
        List<Map<String, Object>> dataList = db.queryMap(builder.toString(), params);
        System.out.println(System.currentTimeMillis() - s);
        return dataList;
    }

    @Override
    public TbyMountainsScreenBean queryBackups(String deviceId, String startTime, String endTime) {
        try {
            List<TbyMountainsScreenBean> dataList = db.table("tby_uav_info_backups").whereEq("derail", 2)
                    .andIf(StringUtils.isNotEmpty(deviceId), "device_id = ?", deviceId)
                    .andIf(StringUtils.isNotEmpty(startTime), "create_time >= ?", startTime + " 00:00:00")
                    .andIf(StringUtils.isNotEmpty(endTime), "create_time <= ?", endTime + " 23:59:59")
                    .selectList("count(id) flight_count, sum(flight_distance) flight_distance, sum(flight_time) flight_time", TbyMountainsScreenBean.class);
            TbyMountainsScreenBean result = TbyMountainsScreenBean.initFlightData();
            if (dataList != null && dataList.size() > 0) {
                result = dataList.get(0);
                result.getFlightTimeHour();
            }
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return TbyMountainsScreenBean.initFlightData();
    }

    @Override
    public Map<Long, TbyUavPointScreenVo> realTrack() {
        try {
            List<TbyUavInfo> uavList = db.table("tby_uav_info").selectList("*", TbyUavInfo.class);
            Map<String, TbyUavPointScreenVo> deviceMap = new HashMap<>(0);
            Map<Long, TbyUavPointScreenVo> map = new HashMap<>(0);
            for (TbyUavInfo uav : uavList) {
                TbyUavPointScreenVo vo = new TbyUavPointScreenVo();
                vo.setDeviceId(uav.getDeviceId());
                vo.setUavId(uav.getId());
                vo.setStatus(uav.getStatus());
                vo.setName(uav.getName());
                vo.setLonLat(uav.getLonLat());
                vo.setPoint("");
                vo.setCode(uav.getCode());
                map.put(uav.getId(), vo);
                deviceMap.put(uav.getDeviceId(), vo);
            }
            List<TbyUavPointScreenVo> dataList = db.table("tby_uav_point").orderBy("id").selectList("id, device_id, point", TbyUavPointScreenVo.class);
            Long maxId = 0L;
            for (TbyUavPointScreenVo backup : dataList) {
                maxId = backup.getId();
                TbyUavPointScreenVo vo = deviceMap.get(backup.getDeviceId());
                if (vo == null) {
                    continue;
                }
                vo.setPoint((vo.getPoint() + " " + backup.getPoint()).trim());
                deviceMap.put(backup.getDeviceId(), vo);
                map.put(vo.getUavId(), vo);
            }
            if (maxId.compareTo(0L) > 0) {
                try {
                    // 读出后删除读出的数
                    db.table("tby_uav_point").whereLte("id", maxId).delete();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            return map;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return new HashMap<>(0);
    }

}
